import numpy as np
from audio_processing.base_processor import AudioProcessor
import threading
import time
from collections import deque


class WaveformViewerProcessor(AudioProcessor):
    """波形查看器处理器"""

    def __init__(self, parameters):
        super().__init__(parameters)
        self.auto_scale = parameters.get('auto_scale', True)
        self.display_time = parameters.get('display_time', 1.0)
        self.y_range = parameters.get('y_range', 1.0)
        self.x_axis_mode = parameters.get('x_axis_mode', 'time')
        self.x_scroll = parameters.get('x_scroll', False)
        self.show_grid = parameters.get('show_grid', True)
        self.refresh_rate = parameters.get('refresh_rate', 20)  # 刷新率（FPS）

        # 波形数据缓存 - 根据显示时间动态调整大小
        self.max_buffer_size = 44100  # 默认1秒的数据（44.1kHz）
        self.waveform_data = deque(maxlen=self.max_buffer_size)
        self.sample_count = 0

        # 显示窗口引用
        self.display_window = None
        self.node_name = "波形查看器"

        # 线程锁
        self.data_lock = threading.Lock()

        # 处理状态
        self.is_processing = False
        self.last_update_time = 0
        self.update_interval = 1.0 / self.refresh_rate  # 根据刷新率计算更新间隔

        # 参数更新回调
        self.parameter_update_callback = None

    def set_sample_rate(self, sample_rate: int):
        """设置采样率并重新计算缓冲区大小"""
        super().set_sample_rate(sample_rate)
        self._update_buffer_size()

    def _update_buffer_size(self):
        """根据显示时间和采样率更新缓冲区大小"""
        if self.sample_rate > 0:
            self.max_buffer_size = int(self.display_time * self.sample_rate)
            # 创建新的deque，保持现有数据
            with self.data_lock:
                old_data = list(self.waveform_data)
                self.waveform_data = deque(maxlen=self.max_buffer_size)
                # 只保留最新的数据
                keep_count = min(len(old_data), self.max_buffer_size)
                self.waveform_data.extend(old_data[-keep_count:])

    def process(self, audio_data: np.ndarray) -> np.ndarray:
        """处理音频数据并缓存波形 - 修复无输入处理"""
        if not self.is_active:
            return audio_data

        # 确保数据形状正确
        audio_data = self._ensure_correct_shape(audio_data)

        # 缓存波形数据用于显示
        with self.data_lock:
            # 将音频数据添加到波形缓存
            for i in range(len(audio_data)):
                # 如果是多通道，取第一个通道
                if audio_data.shape[1] > 0:
                    sample = audio_data[i, 0]
                else:
                    sample = 0.0
                self.waveform_data.append(sample)
                self.sample_count += 1

        # 限制更新频率
        current_time = time.time()
        if current_time - self.last_update_time < self.update_interval:
            return audio_data

        self.last_update_time = current_time

        # 更新显示窗口（如果存在）
        if self.display_window and hasattr(self.display_window, 'update_waveform_signal'):
            try:
                # 获取当前波形数据
                with self.data_lock:
                    waveform = list(self.waveform_data)
                    current_params = {
                        'auto_scale': self.auto_scale,
                        'display_time': self.display_time,
                        'y_range': self.y_range,
                        'x_axis_mode': self.x_axis_mode,
                        'x_scroll': self.x_scroll,
                        'show_grid': self.show_grid,
                        'sample_rate': self.sample_rate
                    }

                # 在UI线程中更新波形
                if waveform:  # 确保有数据
                    self.display_window.update_waveform_signal.emit(waveform, current_params)
                else:
                    # 没有数据时发送空波形
                    self.display_window.update_waveform_signal.emit([], current_params)

            except Exception as e:
                print(f"更新波形显示时出错: {e}")
                import traceback
                traceback.print_exc()

        # 波形查看器通常是直通的（不影响音频信号）
        return audio_data

    def update_parameters(self, new_parameters):
        """更新参数 - 添加范围验证"""
        super().update_parameters(new_parameters)

        old_display_time = self.display_time

        # 🔧 修改：限制参数范围
        self.auto_scale = new_parameters.get('auto_scale', self.auto_scale)

        # 显示时间范围限制：0.01 - 1.00
        new_display_time = new_parameters.get('display_time', self.display_time)
        self.display_time = max(0.01, min(1.00, new_display_time))

        # Y轴范围限制：0.01 - 1.00
        new_y_range = new_parameters.get('y_range', self.y_range)
        self.y_range = max(0.01, min(1.00, new_y_range))

        self.x_axis_mode = new_parameters.get('x_axis_mode', self.x_axis_mode)
        self.x_scroll = new_parameters.get('x_scroll', self.x_scroll)
        self.show_grid = new_parameters.get('show_grid', self.show_grid)
        
        # 更新刷新率参数
        if 'refresh_rate' in new_parameters:
            try:
                refresh_rate = int(new_parameters['refresh_rate'])
                # 限制在有效范围内
                self.refresh_rate = max(5, min(refresh_rate, 20))
                # 更新更新间隔
                self.update_interval = 1.0 / self.refresh_rate
            except (ValueError, TypeError):
                pass

        # 如果显示时间改变，更新缓冲区大小
        if old_display_time != self.display_time and self.sample_rate > 0:
            self._update_buffer_size()

        # 通知显示窗口参数已更新
        if self.display_window and hasattr(self.display_window, 'on_processor_parameters_updated'):
            self.display_window.on_processor_parameters_updated(new_parameters)
            
    def update_parameter_from_display(self, param_name, value):
        """从显示窗口接收参数更新"""
        self.update_parameters({param_name: value})

    def set_display_window(self, window):
        """设置显示窗口"""
        self.display_window = window

    def set_node_name(self, name):
        """设置节点名称"""
        self.node_name = name

    def get_waveform_data(self):
        """获取当前波形数据"""
        with self.data_lock:
            return list(self.waveform_data), self.sample_count

    def reset(self):
        super().reset()
        with self.data_lock:
            self.waveform_data.clear()
            self.sample_count = 0

    def start(self):
        """启动处理器"""
        super().start()
        self.is_processing = True

    def stop(self):
        """停止处理器"""
        super().stop()
        self.is_processing = False

    def set_parameter_update_callback(self, callback):
        """设置参数更新回调"""
        self.parameter_update_callback = callback

    def update_parameter_from_display(self, param_name, value):
        """从显示窗口更新参数"""
        old_value = getattr(self, param_name, None)
        if old_value != value:
            setattr(self, param_name, value)

            # 触发参数更新回调
            if self.parameter_update_callback:
                self.parameter_update_callback(param_name, value)

            # 特殊处理：如果显示时间改变，需要更新缓冲区
            if param_name == 'display_time' and self.sample_rate > 0:
                self._update_buffer_size()
